﻿namespace Siyarem.Database
{
    using Microsoft.Practices.EnterpriseLibrary.Data;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Common;
    using System.Text;

    public abstract class QueryDB
    {
        private int _commandTimeoutSec = 120;
        private DbConnection _connection;
        private Microsoft.Practices.EnterpriseLibrary.Data.Database _database;
        private bool _isInTransaction;
        private Microsoft.Practices.EnterpriseLibrary.Data.ParameterCache _parameterCache;
        private string _query;
        private DbTransaction _transaction;

        public QueryDB(string configKey)
        {
            this._database = DatabaseFactory.CreateDatabase(configKey);
            this._parameterCache = new Microsoft.Practices.EnterpriseLibrary.Data.ParameterCache();
        }

        public void BeginTransaction()
        {
            this._connection = this.Database.CreateConnection();
            this._connection.Open();
            this._transaction = this.Connection.BeginTransaction();
            this._isInTransaction = true;
        }

        private void CacheParameters(DbCommand cmd)
        {
            if (cmd.CommandType == CommandType.StoredProcedure)
            {
                this.ParameterCache.SetParameters(cmd, this.Database);
            }
        }

        public void CommitTransaction()
        {
            this.Transaction.Commit();
            this.Transaction.Dispose();
            this._transaction = null;
            this.Connection.Close();
            this.Connection.Dispose();
            this._connection = null;
            this._isInTransaction = false;
        }

        public bool DataAdapter_Guncelle(DataTable Table, string strSelect)
        {
            bool flag;
            try
            {
                DbCommand command = this._database.DbProviderFactory.CreateCommand();
                command.CommandText = strSelect;
                this._connection = this.Database.CreateConnection();
                this._connection.Open();
                command.Connection = this._connection;
                DbDataAdapter adapter = this._database.DbProviderFactory.CreateDataAdapter();
                adapter.SelectCommand = command;
                DbCommandBuilder builder = this._database.DbProviderFactory.CreateCommandBuilder();
                builder.DataAdapter = adapter;
                builder.ConflictOption = ConflictOption.OverwriteChanges;
                builder.SetAllValues = false;
                adapter.UpdateBatchSize = 0;
                adapter.Update(Table);
                flag = true;
            }
            finally
            {
                this._connection.Close();
            }
            return flag;
        }

        protected DataRow ExecuteForDataRow(string commandText, CommandType cmdType)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            DataTable table = this.Database.ExecuteDataSet(dBCommand).Tables[0];
            if (!this.IsInTransaction)
            {
                if (table.Rows.Count > 0)
                {
                    return this.Database.ExecuteDataSet(dBCommand).Tables[0].Rows[0];
                }
                return null;
            }
            if (table.Rows.Count > 0)
            {
                return this.Database.ExecuteDataSet(dBCommand, this.Transaction).Tables[0].Rows[0];
            }
            return null;
        }

        protected DataRow ExecuteForDataRow(string commandText, CommandType cmdType, List<ParameterPair> parameters)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            DataTable table = this.Database.ExecuteDataSet(dBCommand).Tables[0];
            if (!this.IsInTransaction)
            {
                if (table.Rows.Count > 0)
                {
                    return this.Database.ExecuteDataSet(dBCommand).Tables[0].Rows[0];
                }
                return null;
            }
            if (table.Rows.Count > 0)
            {
                return this.Database.ExecuteDataSet(dBCommand, this.Transaction).Tables[0].Rows[0];
            }
            return null;
        }

        protected DataRow ExecuteForDataRow(string commandText, CommandType cmdType, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            DataTable table = this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0];
            if (table.Rows.Count > 0)
            {
                return this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0].Rows[0];
            }
            return null;
        }

        protected DataRow ExecuteForDataRow(string commandText, CommandType cmdType, List<ParameterPair> parameters, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            DataTable table = this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0];
            if (table.Rows.Count > 0)
            {
                return this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0].Rows[0];
            }
            return null;
        }

        protected DataTable ExecuteForDataTable(string commandText, CommandType cmdType)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteDataSet(dBCommand).Tables[0];
            }
            return this.Database.ExecuteDataSet(dBCommand, this.Transaction).Tables[0];
        }

        protected DataTable ExecuteForDataTable(string commandText, CommandType cmdType, List<ParameterPair> parameters)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteDataSet(dBCommand).Tables[0];
            }
            return this.Database.ExecuteDataSet(dBCommand, this.Transaction).Tables[0];
        }

        protected DataTable ExecuteForDataTable(string commandText, CommandType cmdType, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            return this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0];
        }

        protected DataTable ExecuteForDataTable(string commandText, CommandType cmdType, List<ParameterPair> parameters, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            return this.Database.ExecuteDataSet(dBCommand, transaction).Tables[0];
        }

        protected int ExecuteForNonQuery(string commandText, CommandType cmdType)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteNonQuery(dBCommand);
            }
            return this.Database.ExecuteNonQuery(dBCommand, this.Transaction);
        }

        protected int ExecuteForNonQuery(string commandText, CommandType cmdType, List<ParameterPair> parameters)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteNonQuery(dBCommand);
            }
            return this.Database.ExecuteNonQuery(dBCommand, this.Transaction);
        }

        protected int ExecuteForNonQuery(string commandText, CommandType cmdType, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            return this.Database.ExecuteNonQuery(dBCommand, transaction);
        }

        protected int ExecuteForNonQuery(string commandText, CommandType cmdType, List<ParameterPair> parameters, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            return this.Database.ExecuteNonQuery(dBCommand, transaction);
        }

        protected object ExecuteForScalar(string commandText, CommandType cmdType)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteScalar(dBCommand);
            }
            return this.Database.ExecuteScalar(dBCommand, this.Transaction);
        }

        protected object ExecuteForScalar(string commandText, CommandType cmdType, List<ParameterPair> parameters)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            if (!this.IsInTransaction)
            {
                return this.Database.ExecuteScalar(dBCommand);
            }
            return this.Database.ExecuteScalar(dBCommand, this.Transaction);
        }

        protected object ExecuteForScalar(string commandText, CommandType cmdType, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand);
            return this.Database.ExecuteScalar(dBCommand, transaction);
        }

        protected object ExecuteForScalar(string commandText, CommandType cmdType, List<ParameterPair> parameters, DbTransaction transaction)
        {
            DbCommand dBCommand = this.GetDBCommand(commandText, cmdType);
            this.CacheParameters(dBCommand);
            this.SetQueryParams(dBCommand, parameters);
            return this.Database.ExecuteScalar(dBCommand, transaction);
        }

        private DbCommand GetDBCommand(string commandText, CommandType cmdType)
        {
            DbCommand storedProcCommand;
            if ((cmdType == CommandType.Text) || (cmdType == CommandType.TableDirect))
            {
                storedProcCommand = this.Database.GetSqlStringCommand(commandText);
                storedProcCommand.CommandTimeout = this.CommandTimeoutSec;
                return storedProcCommand;
            }
            if (cmdType != CommandType.StoredProcedure)
            {
                throw new NotImplementedException("Bu t\x00fcrde bir sorgu tanımlı değil");
            }
            storedProcCommand = this.Database.GetStoredProcCommand(commandText);
            storedProcCommand.CommandTimeout = this.CommandTimeoutSec;
            return storedProcCommand;
        }

        public void JoinTransaction(QueryDB transactionStarter)
        {
            if (transactionStarter == null)
            {
                throw new NullReferenceException("Transaction başlatan nesne null olamaz");
            }
            if ((this.Transaction != null) || (this.Connection != null))
            {
                this.Transaction.Rollback();
                this.Transaction.Dispose();
                this._transaction = null;
                this.Connection.Close();
                this.Connection.Dispose();
                this._connection = null;
                throw new InvalidOperationException("Hatalı kullanım. Nesne ile daha \x00f6nce veritabanı işlemi yapılmış.");
            }
            this.Database = transactionStarter.Database;
            this.Connection = transactionStarter.Transaction.Connection;
            this.Transaction = transactionStarter.Transaction;
            this._isInTransaction = true;
        }

        public void RollbackTransaction()
        {
            this.Transaction.Rollback();
            this.Transaction.Dispose();
            this._transaction = null;
            this.Connection.Close();
            this.Connection.Dispose();
            this._connection = null;
            this._isInTransaction = false;
        }

        private void SetQueryParams(DbCommand cmd)
        {
            StringBuilder builder = new StringBuilder(cmd.CommandText);
            builder.Append(";");
            this._query = builder.ToString();
        }

        private void SetQueryParams(DbCommand cmd, List<ParameterPair> parameters)
        {
            StringBuilder builder = new StringBuilder(cmd.CommandText);
            builder.Append(";");
            List<ParameterPair>.Enumerator enumerator = parameters.GetEnumerator();
            while (enumerator.MoveNext())
            {
                this._database.SetParameterValue(cmd, enumerator.Current.Name, enumerator.Current.Value);
                builder.Append(enumerator.Current.Name);
                builder.Append("=");
                builder.Append(enumerator.Current.Value);
                builder.Append(";");
            }
            this._query = builder.ToString();
        }

        public int CommandTimeoutSec
        {
            get
            {
                return this._commandTimeoutSec;
            }
            set
            {
                this._commandTimeoutSec = value;
            }
        }

        public DbConnection Connection
        {
            get
            {
                return this._connection;
            }
            set
            {
                this._connection = value;
            }
        }

        public Microsoft.Practices.EnterpriseLibrary.Data.Database Database
        {
            get
            {
                return this._database;
            }
            set
            {
                this._database = value;
            }
        }

        public bool IsInTransaction
        {
            get
            {
                return this._isInTransaction;
            }
        }

        public Microsoft.Practices.EnterpriseLibrary.Data.ParameterCache ParameterCache
        {
            get
            {
                return this._parameterCache;
            }
        }

        public string Query
        {
            get
            {
                return this._query;
            }
        }

        public DbTransaction Transaction
        {
            get
            {
                return this._transaction;
            }
            set
            {
                this._transaction = value;
            }
        }
    }
}

